package com.nuanshui.heatedloan.service.services;

import com.alibaba.dubbo.config.annotation.Reference;
import com.google.common.collect.Lists;
import com.nuanshui.framework.cache.CacheConstants;
import com.nuanshui.framework.lang.SysStringUtils;
import com.nuanshui.framework.security.MD5Util;
import com.nuanshui.framework.security.RSAUtils;
import com.nuanshui.framework.utils.redis.JedisUtil;
import com.nuanshui.framework.utils.serializer.JavaSerializer;
import com.nuanshui.heatedloan.constant.GlobalParam;
import com.nuanshui.heatedloan.baseservice.enums.FeedMessageType;
import com.nuanshui.heatedloan.baseservice.facade.ActionCountService;
import com.nuanshui.heatedloan.baseservice.facade.BaiduLbsService;
import com.nuanshui.heatedloan.baseservice.model.ActionCount;
import com.nuanshui.heatedloan.baseservice.model.UserAgent;
import com.nuanshui.heatedloan.baseservice.vo.MctXY;
import com.nuanshui.heatedloan.baseservice.vo.MsgStatus;
import com.nuanshui.heatedloan.baseservice.vo.PublishKey;
import com.nuanshui.heatedloan.dal.BaseEntityImpl;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.KeyPair;
import java.security.interfaces.RSAPublicKey;
import java.util.Date;
import java.util.List;

@Component("commonTool")
public class CommonTool {
	protected Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
	private JedisUtil jedisUtil;

	@Reference(url = GlobalParam.BASESERVICE_DUBBO_SERVER, timeout = GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private BaiduLbsService baiduLbsService;

	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;

	@Reference(url = GlobalParam.BASESERVICE_DUBBO_SERVER, timeout = GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private ActionCountService actionCountService;

	public String generateToken(String type) {
		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);
		String version = userAgent.getVersion();
		return generateToken(type, version);
	}

	public String generateToken(String type, String salt) {
		String randomNum = SysStringUtils.getRandomString(6);
		String str = new Date().getTime() + "";
		str = randomNum + str.substring(6);
		String md5Str = MD5Util.md5(str + salt).toLowerCase();
		jedisUtil.hset(CacheConstants.TOKEN_LIST + type, md5Str, "1");
		return str;
	}

	public boolean verifyToken(String type, String token) {
		String str = jedisUtil.hget(CacheConstants.TOKEN_LIST + type, token, String.class);
		return "1".equals(str);

	}

	public MsgStatus getMsgStatus(String userId) {

		MsgStatus msgStatus = new MsgStatus();
		List<FeedMessageType> types = jedisUtil.lrangeAllObj(CacheConstants.FEED_MSG_TYPE + userId,
				FeedMessageType.class);
		if (types != null) {
			for (FeedMessageType type : types) {
				switch (type) {
				case REMIND:
				case REPLY:
				case REPLY_USER:
					msgStatus.setComment(true);
					break;
				case INTERESTED:
					msgStatus.setInterested(true);
					break;
				case LIKE:
				case POST_REPLY_PRAISE:
				case POST_PRAISE:
					msgStatus.setLike(true);
					break;
				case TO_BE_SHIPPED://代发货
				case ORDER_SHIPPED:// 订单已发货
				case ORDER_SIGNED:// 订单已签收
				case BID_SUCCESS:// 成功竞拍
				case RETURN_TO_ACCOUNT:// 退款到账
				case CROWD_FUND_INTEREST_DEPOSIT:// 众筹本息到账
				case DEPOSIT_TO_ACCOUNT:// 保证金退还
				case BID_OVERPASSED:// 出价被超越
				case INTERST_TO_ACCOUNT:// 收益到账
				case NEW_COMMENT:// 新的评论
					msgStatus.setTransShip(true);
					break;
				default:
					break;
				}

			}
		}

		if (jedisUtil.exists(CacheConstants.FEED_MSG_TYPE + "offical")) {
			// 表示有系统消息
			Integer result = jedisUtil.hget(CacheConstants.OFFICAL_USERS_MAP, userId, Integer.class);
			if (result == null) {
				// 表示没有查看过
				msgStatus.setOfficial(true);
			}
		}
		return msgStatus;
	}

	/**
	 * 举例：判断安卓2.6.0 和ios 2.6.0以上执行某个操作， if(commonTool.allowExecute("260","260"))
	 * {
	 * 
	 *
	 * }else {
	 * 
	 * 
	 * 根据版本号和客户端类型判断是否可以执行某些操作
	 * @return
	 */
	public boolean allowExectue(String androidVersion, String iosVersion) {
		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);
		String channel = userAgent.getChannel();

		String c = userAgent.getClient();
		String v = userAgent.getVersion();
		if (c == null)
			return false;
		if (v == null)
			return false;
		v = v.replace(".", "");
		Integer versionInt = Integer.parseInt(v);
		if ("android".equals(c)) {
			Integer androidVersionInt = Integer.parseInt(androidVersion);
			if (versionInt >= androidVersionInt)
				return true;
		} else if (c.startsWith("iPhone")) {
			if (!"TaoWan".equals(channel) && !"appStore".equals(channel))
				return true;
			Integer iosVersionInt = Integer.parseInt(iosVersion);
			if (versionInt >= iosVersionInt) {
				return true;
			}
		}
		return false;

	}

	public enum ClientType {
		UNKNOWN, IOS, ANDROID, WEIXIN
	}

	public ClientType getClient() {

		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);

		String c = userAgent.getClient();
		if (c == null)
			return ClientType.UNKNOWN;

		ClientType type = ClientType.UNKNOWN;

		if (c.startsWith("iPhone")) {
			type = ClientType.IOS;
		} else if (c.startsWith("android")) {
			type = ClientType.ANDROID;
		}

		return type;
	}

	public boolean allowIOSExecute(String iosVersion) {
		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);
		String channel = userAgent.getChannel();
		String c = userAgent.getClient();
		String v = userAgent.getVersion();
		if (c == null)
			return false;
		if (v == null)
			return false;
		v = v.replace(".", "");
		Integer versionInt = Integer.parseInt(v);
		if (c.startsWith("iPhone")) {
			if (!"TaoWan".equals(channel) && !"appStore".equals(channel))
				return true;
			Integer iosVersionInt = Integer.parseInt(iosVersion);
			if (versionInt >= iosVersionInt) {
				return true;
			}
		}
		return false;

	}

	public boolean allowAndroidExecute(String androidVersion) {
		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);

		String c = userAgent.getClient();
		String v = userAgent.getVersion();
		if (c == null)
			return false;
		if (v == null)
			return false;
		v = v.replace(".", "");
		Integer versionInt = Integer.parseInt(v);
		if ("android".equals(c)) {
			Integer androidVersionInt = Integer.parseInt(androidVersion);
			if (versionInt >= androidVersionInt)
				return true;
		}
		return false;

	}

	public Long getMaxId(String key) {
		Long result = null;
		HttpServletRequest request = getServletRequest();
		String page = request.getParameter("page");
		if (SysStringUtils.isEmpty(page))
			return result;
		Integer pageInt = Integer.parseInt(page);
		if (pageInt == 0)
			return result;
		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);
		String safeToken = userAgent.getSafeToken();
		if (SysStringUtils.isEmpty(safeToken))
			return result;
		result = jedisUtil.getObject(safeToken + "_" + key, Long.class);
		return result;
	}

	public void setMaxId(String key, Long maxId) {
		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);
		String safeToken = userAgent.getSafeToken();
		if (SysStringUtils.isEmpty(safeToken))
			return;
		jedisUtil.setObject(safeToken + "_" + key, maxId);
	}

	public String resolveLocation(String longitude, String latitude) {

		String address = null;
		if (!SysStringUtils.isEmpty(longitude)
				&& !SysStringUtils.isEmpty(latitude)) {
			MctXY point = new MctXY();
			point.setLatitude(latitude);
			point.setLongitude(longitude);
			address = baiduLbsService.queryLocation(point);
		}
		return address;
	}

	public String resolveLocation(String longitude, String latitude, HttpServletRequest request) {

		String address = null;
		if (!SysStringUtils.isEmpty(longitude)
				&& !SysStringUtils.isEmpty(latitude)) {
			MctXY point = new MctXY();
			point.setLatitude(latitude);
			point.setLongitude(longitude);
			address = baiduLbsService.queryLocation(point);
		} else {
			address = baiduLbsService.queryLocation(getIpAddr(request));
		}
		return address;
	}

	private static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

	

	/**
	 * 删除缓存的用户信息
	 * 
	 * @param userId
	 */
	public void deleteSimpleUserInfo(String userId) {
		jedisUtil.del(GlobalParam.USER_PREFIX + userId);
	}

	/**
	 * 增加计数
	 */
	public void incrCount(final int type, final String bizId) {
		if (SysStringUtils.isEmpty(type) || SysStringUtils.isEmpty(bizId))
			return;
		String id = "COUNT_" + type + "_" + bizId;
		synchronized (id.intern()) {
			String countStr = jedisUtil.get(id);
			Long count = 0l;
			if (!SysStringUtils.isEmpty(countStr) && !"null".equals(countStr))
				count = Long.parseLong(countStr);
			if (countStr == null || "null".equals(countStr)) {// 如果缓存不存在
				count = actionCountService.getCount(bizId, type);
				if (count == null) {// 如果获取记录为空表示还没有做任何记录
					taskExecutor.execute(new Runnable() {
						@Override
						public void run() {
							ActionCount actionCount = new ActionCount();
							actionCount.setBizId(bizId);
							actionCount.setCount(1l);
							actionCount.setType(type);
							actionCountService.save(actionCount);
						}
					});
					jedisUtil.set(id, "1");
				} else {// 存在记录
					jedisUtil.set(id, (count + 1) + "");
					taskExecutor.equals(new Runnable() {
						@Override
						public void run() {
							actionCountService.incrCount(bizId, type);
						}
					});
				}
			} else {// 缓存存在
				jedisUtil.incr(id);
				taskExecutor.execute(new Runnable() {
					@Override
					public void run() {
						actionCountService.incrCount(bizId, type);
					}
				});
			}
		}
	}

	/**
	 * 获取计数
	 * 
	 * @return
	 */
	public Long getCount(int type, String bizId) {
		String id = "COUNT_" + type + "_" + bizId;
		String countStr = jedisUtil.get(id);
		Long count = 0l;
		if (!SysStringUtils.isEmpty(countStr) && !"null".equals(countStr)) {
			count = Long.parseLong(countStr);
		} else {
			Long result = actionCountService.getCount(bizId, type);
			if (result != null) {
				count = result;
				jedisUtil.set(id, result + "");
			} else {
				jedisUtil.set(id, "0");
			}
		}
		return count;
	}

	/**
	 * 增加计数
	 */
	public void decrCount(final int type, final String bizId) {
		if (SysStringUtils.isEmpty(type) || SysStringUtils.isEmpty(bizId))
			return;
		String id = "COUNT_" + type + "_" + bizId;
		synchronized (id.intern()) {
			String countStr = jedisUtil.get(id);
			Long count = 0l;
			if (!SysStringUtils.isEmpty(countStr) && !"null".equals(countStr))
				count = Long.parseLong(countStr);
			if (countStr == null || "null".equals(countStr)) {// 如果缓存不存在
				count = actionCountService.getCount(bizId, type);
				if (count != null) {//
					jedisUtil.set(id, (count - 11) + "");
					taskExecutor.equals(new Runnable() {
						@Override
						public void run() {
							actionCountService.decrCount(bizId, type);
						}
					});
				}
			} else {// 缓存存在
				jedisUtil.decr(id);
				taskExecutor.execute(new Runnable() {
					@Override
					public void run() {
						actionCountService.decrCount(bizId, type);
					}
				});
			}
		}
	}
	
    
    
    public List<String> getIds(List<? extends BaseEntityImpl> entities) {
        List<String> ids = Lists.newArrayList();
        
        for(BaseEntityImpl entity :entities) {
            ids.add(entity.getId());
        }
        return ids;
    }


	/**
	 * 获取加密的公钥字符串
	 * 
	 * @param
	 * @author guohao
	 * @date 2016年3月14日 下午6:54:44
	 */
	public PublishKey getDefaultPublishKey(String safeToken) {
		KeyPair keyPair = RSAUtils.generateKeyPair();
		try {
			jedisUtil.set("password_public_key_" + safeToken, new JavaSerializer().serialize(keyPair));
		} catch (IOException e) {
			e.printStackTrace();
		}

		if (keyPair != null) {
			PublishKey publishKey = new PublishKey();
			RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
			publishKey.setExponent(new String(Hex.encodeHex(rsaPublicKey.getPublicExponent().toByteArray())));
			publishKey.setModules(new String(Hex.encodeHex(rsaPublicKey.getModulus().toByteArray())));
			return publishKey;
		}
		return null;

	}

	public String decryptPassword(String safeToken, String password) {
		byte[] by = jedisUtil.get(("password_public_key_" + safeToken).getBytes());
		if (by != null) {
			try {
				KeyPair keyPair = (KeyPair) new JavaSerializer().deserialize(by);
				return RSAUtils.decryptString(password, keyPair);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return "";

	}

	/**
	 * 获取用户token
	 * 
	 * @return
	 * @since 1.6.0
	 */
	/*
	 * public boolean hasToken() { UserAgent userAgent = (UserAgent)
	 * getServletRequest().getAttribute(GlobalParam.USER_AGENT); String memberId
	 * = userAgent.getMemberId(); if(memberId == null) return false; String key
	 * = jedisUtil.get(memberId); if(key == null) {
	 * 
	 * } }
	 */

	HttpServletRequest getServletRequest() {
		ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
		return attr.getRequest();
	}

	public UserAgent getUserAgent()
	{
		return (UserAgent) getServletRequest()
				.getAttribute(GlobalParam.USER_AGENT);
	}
	
	/**
	 * 
	 * @param newVersion
	 * @return
	 */
	public boolean compareVersion(String newVersion) {
		
		UserAgent userAgent = (UserAgent) getServletRequest().getAttribute(GlobalParam.USER_AGENT);

		String clientVersion = userAgent.getVersion();
		if (clientVersion == null)
			return false;
		
		//新旧版本分割后的长度是一样的
		String[] newVersions = newVersion.split("\\.");
		String[] clientVersions = clientVersion.split("\\.");
		
		//true表示有新版本
		boolean flag = false;
		for (int i=0; i<newVersions.length; i++) {
			int nv = Integer.parseInt(newVersions[i]);
			int cv = Integer.parseInt(clientVersions[i]);
			if (nv > cv) {
				flag = true;
				break;
			}
			if (nv < cv){
				flag = false;
				break;
			}
		}
		return flag;
	}
}
